#region Copyright
/// <copyright>
/// Copyright (c) 2007 Ilia Shramko.
/// Released under the terms of the GNU General Public License.
/// </copyright>
#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Remoting;
using System.Security;
using System.Security.Policy;
using System.Text;
using System.Web;
using System.Web.Hosting;

namespace OshHost.Web
{
    public class WebHost
    {
		private static WebHost _current;
		private OshProtocol _oshProtocol;
		private TraceSource _traceSource;

        public WebHost()
        {
			_traceSource = new TraceSource("OshHost.Web.WebHost");
		}

		public void RegisterOshProtocol()
		{
			_oshProtocol = new OshProtocol();
			_oshProtocol.Register();
		}

		public void Initialize()
		{
			InitializeAppDomain();
			InitializeWebHostingEnvironment();

			// For some reason .png extension is not registered in the global mime map by default.
			// Without this registered ASP will return "Content-Type: application/octet-stream".
			AddMimeMapping(".png", "image/png");


			// Set AppDomain shutdown event handler. For debugging purpose only
			FieldInfo httpRuntimeField = typeof(HttpRuntime).GetField("_theRuntime",
				BindingFlags.NonPublic | BindingFlags.Static);

			HttpRuntime httpRuntime = httpRuntimeField.GetValue(null) as HttpRuntime;

			EventInfo shutdownEvent = typeof(HttpRuntime).GetEvent("AppDomainShutdown",
				BindingFlags.NonPublic | BindingFlags.Static);
			
			MethodInfo addEventMethod = shutdownEvent.GetAddMethod(true);
			addEventMethod.Invoke(null, new object[] { 
				new System.Web.Compilation.BuildManagerHostUnloadEventHandler(this.OnAppDomainShutdown) } );
		}

		void OnAppDomainShutdown(object o, System.Web.Compilation.BuildManagerHostUnloadEventArgs args)
		{
			FieldInfo httpRuntimeField = typeof(HttpRuntime).GetField("_theRuntime",
				BindingFlags.NonPublic | BindingFlags.Static);

			object httpRuntime = httpRuntimeField.GetValue(null);
			Trace.WriteLine("AppDomain shutdown");
		}

		private void InitializeAppDomain()
		{
			string appPath = 
				Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.StartupPath), "Html");

			AppDomain domain = AppDomain.CurrentDomain;
			domain.SetData(".appDomain", "*");
			string domainId = DateTime.Now.GetHashCode().ToString("x");
			domain.SetData(".appId", domainId);
			domain.SetData(".domainId", domainId);
			domain.SetData(".appPath", appPath);
			domain.SetData(".appVPath", "/");
		}

		private void InitializeWebHostingEnvironment()
		{
			HostingEnvironment environment = new HostingEnvironment();

			Type hostingEnvironmentType = Assembly.GetAssembly(typeof(HostingEnvironment))
				.GetType("System.Web.Hosting.SimpleConfigMapPathFactory");

			object map = Activator.CreateInstance(hostingEnvironmentType);

			MethodInfo method = typeof(HostingEnvironment).GetMethod("Initialize",
				BindingFlags.NonPublic | BindingFlags.Instance);
			method.Invoke(environment, new object[] { null, null, map, null });
		}

		private void AddMimeMapping(string extention, string mimeType)
		{
			Type mimeMappingType = Assembly.GetAssembly(typeof(DefaultHttpHandler))
				.GetType("System.Web.MimeMapping");
			MethodInfo method = mimeMappingType.GetMethod("AddMimeMapping",
				BindingFlags.NonPublic | BindingFlags.Static);
			method.Invoke(null, new object[] { extention, mimeType });
		}

		public TraceSource TraceSource
		{
			get { return _traceSource; }
		}

		public static WebHost Current
		{
			get
			{
				if(_current == null)
					_current = new WebHost();
				return _current;
			}
		}
	}
}
